package com.siteseat.common.foundation;

import java.util.concurrent.atomic.AtomicBoolean;

import com.siteseat.common.exception.InternalException;

/**
 * TODO: 1. how to avoid data corruption when data may be partially written to
 * disk during write()/flush()? trace file length? 2. rate measuring
 */
public abstract class Actor extends Component implements Runnable {

  private AtomicBoolean running = new AtomicBoolean( false );
  private AtomicBoolean toStop = new AtomicBoolean( false );

  public void stopRun() {
    this.toStop.set( true );
  }
  
  public boolean toStop() {
    return this.toStop.get();
  }
  
  /**
   * Gets the running
   * 
   * @return the running
   */
  public final boolean isRunning() {
    return running.get();
  }

  /**
   * Sets the running
   * 
   * @param running
   *          the running to set
   */
  private void setRunning( boolean running ) {
    this.running.set( running );
  }

  /**
   * 
   */
  protected abstract void doRun();

  /**
   * 
   */
  public void ensureNotRunning() {
    if( isRunning() == true ) {
      throw new InternalException( "Running already" );
    }
  }

  /**
   * 
   */
  public void ensureRunning() {
    if( isRunning() == false ) {
      throw new InternalException( "Not yet running" );
    }
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public void run() {
    try {
      ensureInited();  
      
      ensureNotRunning();
      setRunning( true );
  
      doRun();
    } catch( Exception e ) {
      log.warn( "Stop to run due to error", e );
    } finally {
      setRunning( false );
    }
  }

}
